package collector

import (
	"encoding/json"
	"github.com/gomodule/redigo/redis"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/log"
	"strconv"
)

type rancherServiceCollector struct {
	Service *prometheus.Desc
}

func init() {
	registerCollector("service", defaultEnabled, rancherServiceExporter)
}

func rancherServiceExporter() (Collector, error) {
	return &rancherServiceCollector{
		Service: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "service", "state"),
			"rancher service state",
			[]string{
				"resource_id",
				"service_name",
				"rancher_env",
				"uuid",
			},
			prometheus.Labels{
				"state_code_removed":      strconv.FormatFloat(Removed, 'f', -1, 64),
				"state_code_inactive":     strconv.FormatFloat(Inactive, 'f', -1, 64),
				"state_code_activating":   strconv.FormatFloat(Activating, 'f', -1, 64),
				"state_code_started_once": strconv.FormatFloat(StartedOnce, 'f', -1, 64),
				"state_code_active":       strconv.FormatFloat(Active, 'f', -1, 64),
				"state_code_upgraded":     strconv.FormatFloat(Upgraded, 'f', -1, 64),
				"state_code_upgrading":    strconv.FormatFloat(Upgrading, 'f', -1, 64),
				"state_code_degraded":    strconv.FormatFloat(Degraded, 'f', -1, 64),
			},
		),
	}, nil
}

func (rc rancherServiceCollector) Update(ch chan<- prometheus.Metric) error {

	services, err := rc.GetServices()

	if err != nil {
		return err
	} else {
		for _, service := range services {
			state := 0.0
			switch service.CombineState {
			case "removed":
				state = Removed
			case "started-once":
				state = StartedOnce
			case "active":
				state = Active
			case "activating":
				state = Activating
			case "inactive":
				state = Inactive
			case "upgrading":
				state = Upgrading
			case "upgraded":
				state = Upgraded
			case "degraded":
				state = Degraded
			}
			ch <- prometheus.MustNewConstMetric(rc.Service, prometheus.GaugeValue, state,
				service.Id,
				service.Name,
				service.RancherEnv,
					service.Uuid,
			)
		}
	}
	return nil
}

func (rc rancherServiceCollector) GetServices() (services []*Service, err error) {
	c := RedisPool.Get()
	if c.Err() != nil {
		log.Error(c.Err())
		return nil, c.Err()
	}
	defer c.Close()

	keys, err := redis.Strings(c.Do("KEYS", "service_*"))

	for _, key := range keys {
		ct, err := redis.Bytes(c.Do("GET", key))

		if err != nil {
			log.Error(err)
		} else {
			service := new(Service)
			json.Unmarshal(ct, &service)
			services = append(services, service)
		}
	}
	return services, err
}
